
package com.ctrip.corp.obt.shard.holder;

import com.ctrip.corp.obt.generic.utils.StringPool;
import com.ctrip.corp.obt.shard.annotation.PageQuery;
import com.ctrip.corp.obt.shard.context.PageContext;
import lombok.Builder;
import lombok.Data;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Page辅助类
 *
 * @author marco.zheng
 * @since 2022-03-15
 */
public abstract class PageHolder {

    /**
     * SQL 解析缓存
     * key 可能是 mappedStatement 的 ID,也可能是 class 的 name
     */
    private static final Map<String, PageHolder.PageQueryCache> PAGE_CACHE = new ConcurrentHashMap<>();

    /**
     * 初始化缓存
     * <p>
     * Mapper#method 上 Page 注解信息
     *
     * @param method           Method
     */
    public static void initPageCache(String mapperClassName, Method method) {
        PageQuery pageQuery = method.getAnnotation(PageQuery.class);
        String key = mapperClassName.concat(StringPool.DOT).concat(method.getName());
        if (pageQuery != null) {
            PAGE_CACHE.put(key, buildPageQueryCache(pageQuery));
        }
    }

    /**
     * 是否进行分页操作
     * @return true 是 false 否
     */
    public static boolean needPage(String id) {
        return Objects.nonNull(PAGE_CACHE.get(id)) || PageContext.getPage() != null;
    }

    public static boolean optimizeCountSql(String id) {
        return PAGE_CACHE.get(id).isOptimizeCountSql();
    }

    public static boolean searchCount(String id) {
        return PAGE_CACHE.get(id).isSearchCount();
    }

    public static boolean optimizeJoinOfCountSql(String id) {
        return PAGE_CACHE.get(id).isOptimizeJoinOfCountSql();
    }

    public static String countId(String id) {
        return PAGE_CACHE.get(id).getCountId();
    }

    public static long maxLimit(String id) {
        return PAGE_CACHE.get(id).getMaxLimit();
    }

    public static PageQueryCache getPageQuery(String id) {
        return PAGE_CACHE.get(id);
    }

    private static PageHolder.PageQueryCache buildPageQueryCache(PageQuery page) {
        return PageQueryCache.builder()
                .optimizeCountSql(page.optimizeCountSql())
                .searchCount(page.searchCount())
                .optimizeJoinOfCountSql(page.optimizeJoinOfCountSql())
                .countId(page.countId())
                .maxLimit(page.maxLimit())
                .build();
    }

    @Data
    @Builder
    public static class PageQueryCache {
        /**
         * 自动优化 COUNT SQL
         */
        private boolean optimizeCountSql;

        /**
         * 是否进行 count 查询
         */
        private boolean searchCount;

        /**
         * 是否优化join sql的count sql(目前只支持left join)
         */
        private boolean optimizeJoinOfCountSql;

        /**
         * 自定义的用于分页count的MappedStatement id
         */
        private String countId;

        /**
         * maxLimit 限制条数
         */
        private long maxLimit;
    }

    private PageHolder() {}

}
